<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>mini logo</title>

<script type="text/javascript" src="http://hello-mine.googlecode.com/svn/trunk/jquery.js"></script>
<!--[if IE]><script type="text/javascript" src="http://hello-mine.googlecode.com/svn/trunk/excanvas.js"></script><![endif]-->
<script type="text/javascript">


//global status

var curr_pos={};
curr_pos.x=0;
curr_pos.y=0;
var curr_dir=90;//up;
var pen_status=0;//0 for pendown,1 for penup
var turtle_status=0;//0 for show,1 for hide

var x_center=150;
var y_center=150;


var color_table=[ "#000000","#0000FF","#00FF00","#00FFFF","#FF0000","#FF00FF","#FF8000","#BDBDBD",
"#848484","#8181F7","#81F7BE","#A9F5A9","#FE2E9A","#F781F3","#FFFF00","#FFFFFF"];

var fg_index=0;
var bg_index=15;

var token_type={
  unknown:0,
  symbol:1,
  list:2
};

var symbol_type={
  unkonwn:0,
  number:1,
  variable:2,
  word:3
};

var proc_sys={};
function fd_fun(){
  var fd_length;
  fd_length=arguments[0];
  var ctx1=document.getElementById("board").getContext("2d");
  ctx1.strokeStyle=color_table[fg_index];
  ctx1.lineWidth = "1";
  if(pen_status==0)
  {
    ctx1.beginPath();
    ctx1.moveTo(x_center+curr_pos.x,y_center-curr_pos.y);
  }
  curr_pos.x=curr_pos.x+fd_length*Math.cos(curr_dir*Math.PI/180);
  //curr_pos.x=parseInt(curr_pos.x);
  curr_pos.y=curr_pos.y+fd_length*Math.sin(curr_dir*Math.PI/180);
  //curr_pos.y=parseInt(curr_pos.y);
  if(pen_status==0)
  {
    ctx1.lineTo(x_center+curr_pos.x,y_center-curr_pos.y);
    ctx1.closePath();
    ctx1.stroke();
    
  }
}
function bk_fun(){
  var bk_length;
  bk_length=arguments[0];
  var ctx1=document.getElementById("board").getContext("2d");
  ctx1.strokeStyle=color_table[fg_index];
  ctx1.lineWidth = "1";
  if(pen_status==0)
  {
    ctx1.beginPath();
    ctx1.moveTo(x_center+curr_pos.x,y_center-curr_pos.y);
  }
  curr_pos.x=curr_pos.x-bk_length*Math.cos(curr_dir*Math.PI/180);
  //curr_pos.x=parseInt(curr_pos.x);
  curr_pos.y=curr_pos.y-bk_length*Math.sin(curr_dir*Math.PI/180);
  //curr_pos.y=parseInt(curr_pos.y);
  if(pen_status==0)
  {
    ctx1.lineTo(x_center+curr_pos.x,y_center-curr_pos.y);
    ctx1.stroke();
    ctx1.closePath();
  }
}
function rt_fun(){
  var rt_dir=arguments[0];
  curr_dir=(curr_dir-rt_dir+360)%360;
}
function lt_fun(){
  var lt_dir=arguments[0];
  curr_dir=(curr_dir+lt_dir+360)%360;
}
function pu_fun(){
  pen_status=1;
}
function pd_fun(){
  pen_status=0;
}
function ht_fun(){
  turtle_status=1;
}
function st_fun(){
  turtle_status=0;
}

function setpc_fun(){
  var new_index=arguments[0];
  fg_index=parseInt(Math.abs(new_index))%16;
}

function setbg_fun(){
  var new_index=arguments[0];
  bg_index=parseInt(Math.abs(new_index))%16;
  var ctx1=document.getElementById("board").getContext("2d");
  ctx1.fillStyle=color_table[bg_index];
  ctx1.beginPath();
  ctx1.rect(0,0,300,300);
  ctx1.closePath();
  ctx1.fill();
}

function home_fun(){
  var ctx1=document.getElementById("board").getContext("2d");
  ctx1.lineWidth = "1";
  //ctx1.fillStyle=color_table[fg_index];
  ctx1.strokeStyle=color_table[fg_index];
  if(pen_status==0)
  {
    ctx1.beginPath();
    ctx1.moveTo(x_center+curr_pos.x,y_center-curr_pos.y);
  }
  curr_pos.x=0;
  curr_pos.y=0;
  if(pen_status==0)
  {
    ctx1.lineTo(x_center+curr_pos.x,y_center-curr_pos.y);
    ctx1.closePath();
    ctx1.stroke();
  }
}
function draw_fun(){
  fg_index=0;bg_index=15;
  var ctx1=document.getElementById("board").getContext("2d");
  ctx1.fillStyle=color_table[bg_index];
  ctx1.beginPath();
  ctx1.rect(0,0,300,300);
  ctx1.closePath();
  ctx1.fill();
  curr_pos.x=0;
  curr_pos.y=0;
  curr_dir=90;
}

function cs_fun(){
  var ctx1=document.getElementById("board").getContext("2d");
  ctx1.fillStyle=color_table[bg_index];
  ctx1.beginPath();
  ctx1.rect(0,0,300,300);
  ctx1.closePath();
  ctx1.fill();
  curr_pos.x=0;
  curr_pos.y=0;
  curr_dir=90;
}


proc_sys["fd"]={
  arg_type:[token_type.symbol],
  proc_fun:fd_fun
}
proc_sys["forward"]={
  arg_type:[token_type.symbol],
  proc_fun:fd_fun
}
proc_sys["bk"]={
  arg_type:[token_type.symbol],
  proc_fun:bk_fun
}
proc_sys["back"]={
  arg_type:[token_type.symbol],
  proc_fun:bk_fun
}
proc_sys["rt"]={
  arg_type:[token_type.symbol],
  proc_fun:rt_fun
}
proc_sys["right"]={
  arg_type:[token_type.symbol],
  proc_fun:rt_fun
}
proc_sys["lt"]={
  arg_type:[token_type.symbol],
  proc_fun:lt_fun
}
proc_sys["left"]={
  arg_type:[token_type.symbol],
  proc_fun:lt_fun
}
proc_sys["pu"]={
  arg_type:[],
  proc_fun:pu_fun
}
proc_sys["penup"]={
  arg_type:[],
  proc_fun:pu_fun
}
proc_sys["pd"]={
  arg_type:[],
  proc_fun:pd_fun
}
proc_sys["pendown"]={
  arg_type:[],
  proc_fun:pd_fun
}
proc_sys["ht"]={
  arg_type:[],
  proc_fun:ht_fun
}
proc_sys["hideturtle"]={
  arg_type:[],
  proc_fun:ht_fun
}
proc_sys["st"]={
  arg_type:[],
  proc_fun:st_fun
}
proc_sys["showturtle"]={
  arg_type:[],
  proc_fun:st_fun
}
proc_sys["setpc"]={
  arg_type:[token_type.symbol],
  proc_fun:setpc_fun
}
proc_sys["setbg"]={
  arg_type:[token_type.symbol],
  proc_fun:setbg_fun
}
proc_sys["home"]={
  arg_type:[],
  proc_fun:home_fun
}
proc_sys["draw"]={
  arg_type:[],
  proc_fun:draw_fun
}
proc_sys["cs"]={
  arg_type:[],
  proc_fun:cs_fun
}
proc_sys["cleanscreen"]={
  arg_type:[],
  proc_fun:cs_fun
}

proc_sys["repeat"]={
  arg_type:[token_type.symbol,token_type.list],
  proc_fun:function(){
    var times=arguments[0];
    var cmd_str=arguments[1];
    var next_pos_bak=next_pos;
    var curr_line_bak=curr_proc.proc_line;
    for(var i=0;i<times && is_running;i++)
    {
      exec(cmd_str+" ");
    }
    next_pos=next_pos_bak;
    curr_proc.proc_line=curr_line_bak;
  }
}


var curr_proc={};
//curr_proc.name=""
//curr_proc.line=0;
curr_proc.proc_line="";


//status for current line
var next_pos=0;

var alpha_table=['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
                  'p','q','r','s','t','u','v','w','x','y','z',
                  'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
                  'P','Q','R','S','T','U','V','W','X','Y','Z'];
var number_table=['0','1','2','3','4','5','6','7','8','9'];

var sign_table=['+','-','*','/'];

var bracket_table=['(',')','[',']'];

function get_token()
{
  //line=proc_usr[curr_proc.name].proc_lines[curr_proc.line];
  var line=curr_proc.proc_line;
  var i=next_pos;
  //trim space
  while(line.charAt(i)==' ' && i<line.length)
  {
    i++;
  }
  if(i>=line.length)
  {
    next_pos=-1;//a special sign,maybe 0 for next line
    return "";
  }
  
  
  if((/[a-zA-Z]/).test(line.charAt(i)))//proc
  {
    
    var p_begin=i;
    i=i+1;
    while((/[a-zA-Z]/).test(line.charAt(i)) || (/[0-9]/).test(line.charAt(i)))
    {
      i++;
    }
    next_pos=i
    return line.substring(p_begin,i);
  }
  if((/[0-9]/).test(line.charAt(i)))//number
  {
    var n_begin=i;
    i=i+1;
    while((/[0-9]/).test(line.charAt(i)))
    {
      i++;
    }
    next_pos=i
    return line.substring(n_begin,i);
  }
  
  if(line.charAt(i) =='[' || line.charAt(i)==']')//brackets
  {
    next_pos=i+1;
    return line.charAt(i);
  }
  
  return -1;
}


var is_running;
var err;
function error(err_str)
{
  alert(err_str);
  is_running=false;
  err=1;
}
//just the sys procs,all have no output,so the text area is no need
function exec(cmd_str)
{
  //is_running=true;
  var m_got=0;
  curr_proc.proc_line=cmd_str;
  next_pos=0;
  //while(proc_stack.length>0 && isrunning)
  {
    //while(is_running && curr_proc.line<proc_user[curr_proc.name].lines.length)//for every line
    {
      //what to do here is to get the expr
      
      //while(next_pos<proc_user[curr_proc.name].lines[curr_proc.line].length && next_pos!=-1)
      while(is_running && next_pos<curr_proc.proc_line.length && next_pos!=-1)
      {
        //var last_token_type; just the curr_expr[curr_expr.length-1]
        var token=get_token();

        if(next_pos==-1)return;//finished
        
        var proc_name=token.toLowerCase();
        if(!((/[a-zA-Z]/).test(token[0])))
        {
          error("expecting a sys proc");
          return;
        }
        if(proc_sys[proc_name]==undefined)
        {
          error("bad proc name");
          return;
        }
        var arg_len=proc_sys[proc_name].arg_type.length;
        args=[];
        for(i=0;i<arg_len;i++)
        {
          if(proc_sys[proc_name].arg_type[i]==token_type.list)
          {
            //read the whole list as a string;
            m_got=0;
            list=[];
            do{
              token=get_token();
              if(token=="[")m_got++;
              if(token=="]")m_got--;
              list.push(token);
            }while(m_got>0 && next_pos<curr_proc.proc_line.length && next_pos>=0);
            if(list[0] !== '[' || list[list.length-1]!=']' || m_got>0 )
            {
              error("bad list for"+proc_name);
            }
            list[0]="";list.pop();
            args[i]=list.join(" ");
          }
          else //just read a  number
          {
            token=get_token();
            if(next_pos==-1)
            {
              error("not enough argument(s) for "+proc_name)
            }
            if(isNaN(token))
            {
              error("expecting number for"+proc_name);
              return;
            }
            args[i]=parseInt(token);//just parse Int
          }
        }
        if(arg_len==0)
        {
          proc_sys[proc_name].proc_fun();
        }
        if(arg_len==1)
        {
          proc_sys[proc_name].proc_fun(args[0]);
        }
        if(arg_len==2)
        {
          proc_sys[proc_name].proc_fun(args[0],args[1]);
        }
      }//one line

    }//one user proc
    //one user proc is over,pop the stack and set the status
  }//the whole program
  
}
function drawt()
{
  var ctx1=document.getElementById("turtle").getContext("2d");
  
    ctx1.clearRect(0,0,300,300);
  if(turtle_status==0)
  {
    ctx1.fillStyle=color_table[fg_index];
    ctx1.strokeStyle=color_table[fg_index];
    ctx1.beginPath();
 
    var x1,y1,x2,y2,x3,y3;
    
    x1=curr_pos.x+10*Math.cos(curr_dir*Math.PI/180);
    y1=curr_pos.y+10*Math.sin(curr_dir*Math.PI/180);
    x2=curr_pos.x+4*Math.cos((curr_dir+100)*Math.PI/180);
    y2=curr_pos.y+4*Math.sin((curr_dir+100)*Math.PI/180);
    x3=curr_pos.x+4*Math.cos((curr_dir-100)*Math.PI/180);
    y3=curr_pos.y+4*Math.sin((curr_dir-100)*Math.PI/180);

    ctx1.moveTo(x_center+x1,y_center-y1);
    ctx1.lineTo(x_center+x2,y_center-y2);
    ctx1.lineTo(x_center+x3,y_center-y3);
    ctx1.closePath();
    ctx1.fill();
  }
}
var istimeout=0;
function timeout()
{
  istimeout=1;
  error("Timeout,may be there is a bad loop");
}
$("document").ready(function(){

  drawt();
  $("#cmd_line").keypress(function(){
    var event=(arguments[0]);
    var cmd_str;
    if(event.which==13)
    {
      istimeout=0;
      var timer_handle=setTimeout("timeout()",1000);
      cmd_str=$("#cmd_line").val();
      err=0;
      is_running=true;
      exec(cmd_str+"  ");
      drawt();
      if(err==0)
      {
        $("#cmd_line").val("");
        $("#cmd_line").focus();
      }
      if(istimeout==0)
      {
        clearTimeout(timer_handle);
      }
    }
  });
  $("#cmd_line").focus();
});
</script>
<style type="text/css">
canvas{
height:300px;
width:300px;
border:solid;
}
</style>
</head>
<body>
<div style="align:center;width:300px;height:310px">
<canvas id="board" width="300" height="300" style="position:absolute;top:10px;left:10px;z-index:1">
</canvas>
<canvas id="turtle" width="300" height="300" style="position:absolute;top:10px;left:10px;z-index:100">
</canvas>
</div>
<input type="text" id="cmd_line" size="45" style="width:300px" />
</body>
</html>